package com.aaa.sbm.util;

import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.util.StringUtils;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class MyCustomCache implements Cache {

    //私有静态属性，方便赋值
    private static JedisConnectionFactory jedisConnectionFactory;

    //mybatis官网要求必须有一个String id属性并且通过构造赋值
    private String id;

    //读写数据策略  读读共享  读写互斥  写读互斥  写写互斥
    private ReadWriteLock readWriteLock=new ReentrantReadWriteLock();

    /**
     * 构造赋值
     * @param id
     */
    public MyCustomCache(String id){
        if(StringUtils.isEmpty(id)){
            throw new IllegalArgumentException("id不能为空！");
        }
        this.id=id;
    }

    /**
     * 使用静态方法，初始化JedisConnectionFactory对象
     * @param jedisConnectionFactory
     */
    public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory){
        MyCustomCache.jedisConnectionFactory=jedisConnectionFactory;
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void putObject(Object key, Object value) {
        //通过工厂类获取连接对象
        RedisConnection connection=null;
        try {
            connection = jedisConnectionFactory.getConnection();
            //实例化对象  序列化key 和  value
            JdkSerializationRedisSerializer jdkSerializationRedisSerializer =
                    new JdkSerializationRedisSerializer();
            byte[] skey = jdkSerializationRedisSerializer.serialize(key);
            byte[] svalue = jdkSerializationRedisSerializer.serialize(value);
            //操作redis集群  添加数据
            connection.set(skey,svalue);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(connection!=null){
                connection.close();
            }
        }

    }

    @Override
    public Object getObject(Object key) {
        RedisConnection connection=null;
        try {
            //通过工厂类获取连接对象
            connection = jedisConnectionFactory.getConnection();
            //实例化对象  序列化key 和  value
            JdkSerializationRedisSerializer jdkSerializationRedisSerializer =
                    new JdkSerializationRedisSerializer();
            byte[] skey = jdkSerializationRedisSerializer.serialize(key);
            //操作redis集群  获取数据  得到是序列化后的值
            byte[] valueBytes = connection.get(skey);
            //需要饭序列化
            return jdkSerializationRedisSerializer.deserialize(valueBytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(connection!=null){
                connection.close();
            }
        }

        return null;
    }

    @Override
    public Object removeObject(Object key) {
        RedisConnection connection=null;
        try {
            //通过工厂类获取连接对象
            connection = jedisConnectionFactory.getConnection();
            //实例化对象  序列化key 和  value
            JdkSerializationRedisSerializer jdkSerializationRedisSerializer =
                    new JdkSerializationRedisSerializer();
            byte[] skey = jdkSerializationRedisSerializer.serialize(key);
            //直接删除效率低
            //return connection.del(skey);
            //让key立马失效。并非立马删除，它会批量删除
            return connection.expireAt(skey,0);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(connection!=null){
                connection.close();
            }
        }
        return null;
    }

    @Override
    public void clear() {
        RedisConnection connection=null;
        try {
            //通过工厂类获取连接对象
           connection = jedisConnectionFactory.getConnection();
           //清空当前节点库
           connection.flushDb();
           //清空所有节点库
           connection.flushAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(connection!=null){
                connection.close();
            }
        }
    }

    @Override
    public int getSize() {
        RedisConnection connection=null;
        try {
            //通过工厂类获取连接对象
            connection = jedisConnectionFactory.getConnection();
            //获取当前缓存中的所有对象个数
            Long aLong = connection.dbSize();
            //把long转为int
            return Integer.valueOf(aLong.toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(connection!=null){
                connection.close();
            }
        }
        return 0;
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return readWriteLock;
    }
}
